package extend.db.base;

import extend.db.DbConnection;
import extend.db.DbManager;
import extend.db.build.sql.Union;
import extend.db.util.DbUtil;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * sql 命令类
 *<B>说明：</B>
 *<pre>
 *  jdbc 与实体类通讯 使用此类
 *</pre>
 *<B>示例：</B>
 *<pre>
 *  略
 *</pre>
 *<B>日志：</B>
 *<pre>
 *  略
 *</pre>
 *<B>注意事项：</B>
 *<pre>
 *  略
 *</pre>
 */
public class Query
{
    // 缓存一下字段
    private static Field[] fields = null;

    public static final String TABLE_SET = "table";
    public static final String DATA_SET = "data";
    public static final String WHERE_SET = "where";
    public static final String FIELD_SET = "field";
    public static final String ALIAS_SET = "alias";
    public static final String JOIN_SET = "join";
    public static final String LOCK_SET = "lock";
    public static final String ORDER_SET = "order";
    public static final String LIMIT_SET = "limit";
    public static final String DISTINCT_SET = "distinct";
    public static final String GROUP_SET = "group";
    public static final String HAVING_SET = "having";
    public static final String SOCPE_SET = "socpe";
    public static final String REPLACE_SET = "replace";
    public static final String OFFSET_SET = "offset";
    public static final String DBKEY_SET = "dbkey";


    public static final String BUILD_INSERT = "insert";

    public static final String BUILD_INSERT_ALL = "insertAll";

    public static final String BUILD_UPDATE = "update";

    public static final String BUILD_DELETE = "delete";

    public static final String BUILD_SELECT = "select";

    /**
     * 添加操作数据
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected List<Map<String,Object>> data = null;

    /**
     * 条件
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected Map<String,Object> where = null;

    /**
     * 表名
     *<B>说明：</B>
     *<pre>
     *  不带前缀
     *</pre>
     */
    protected String table = "";

    /**
     * 表别名
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected String alias = "";

    /**
     * 查询字段
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected Object field = null;

    /**
     * 排序规则
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected Map<String,Object> orderBy = null;

    /**
     * 分组规则
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected String[] groupBy = null;

    /**
     * 分组条件
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected Map<String,Object> having = null;

    /**
     * 是否加锁
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected boolean lock = false;

    /**
     * 联合查询
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected Union union;


    /**
     *更新行数
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected int limit = 0;

    /**
     * 起始行数
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected int offset = 0;

    /**
     * 当前操作是否写
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected Boolean isWrite = false;

    protected boolean toQuery = false;

    /**
     * 当前对应的db key
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected String dbkey = "";

    /**
     * QueryBuilder 方法名称
     *<B>说明：</B>
     *<pre>
     *  比如insert 方法
     *</pre>
     */
    protected String buildMethod = "";

    /**
     * QueryBuilder 方法参数
     *<B>说明：</B>
     *<pre>
     *  比如insert 方法
     *</pre>
     */
    protected Object[] buildParams;

    /**
     * 实体类
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected Class entity;

    /**
     * sql 执行结果
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    private Object result = null;

    public Query(){};

    /**
     * 构造方法
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @param attrs
     */
    public Query(Map<String,Object> attrs)
    {
        DbUtil.attr(attrs,this);
    }

    public void setAttrs(Map<String,Object> attrs)
    {
        DbUtil.attr(attrs,this);
    }

    /**
     * 获取当前db连接对象
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return 数据库连接对象
     */
    public DbConnection getDb()
    {
        DbConnection dbConn = DbManager.get().getDb(this.isWrite,this.dbkey);

        return dbConn;
    }

    /**
     * 设置更新标志
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @param update 是否写
     */
    public void toUpdate(Boolean update)
    {
        this.isWrite = update;
    }

    /**
     * 构建Command命令
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return
     */
    public Command buildParamsCommand()
    {
        try {
            DbConnection dbConnection = this.getDb();
            return dbConnection.getQueryBuilder().buildParamsCommand(this);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     *获取QueryBuilder 方法,参数
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return
     */
    public Object[] getBuild()
    {
        return  new Object[]{this.buildMethod,this.buildParams};
    }

    /**
     * 设置返回结果
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @param result
     * @return
     */
    public void setResult(Object result)
    {
        this.result = result;
    }

    /**
     * 获取返回结果
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return
     */
    public Object getResult()
    {
        return this.result;
    }

    public void setDbkey(String dbkey)
    {
        this.dbkey = dbkey;
    }

    public String getDbkey()
    {
        return this.dbkey;
    }

    /**
     * 获取表名
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return
     */
    public String getTable()
    {
        return  this.table;
    }

    public void setTable(String tableName)
    {
        this.table = tableName;
    }

    /**
     * 获取表别名
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return
     */
    public String getAlias()
    {
        return this.alias;
    }

    public void setAlias(String alias)
    {
        this.alias = alias;
    }

    /**
     * 获取查询字段
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return
     */
    public Object getField()
    {
        return  this.field;
    }

    public void setField(Object field)
    {
        this.field = field;
    }

    /**
     * 获取排序规则
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return
     */
    public Map<String,Object> getOrderBy()
    {
        return  this.orderBy;
    }

    public void setOrderBy(Map<String,Object> orderBy)
    {
        if (this.orderBy == null) {
            this.orderBy = orderBy;
        } else {
            this.orderBy.putAll(orderBy);
        }
    }

    /**
     * 获取分组规则
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return
     */
    public String[] getGroupBy()
    {
        return  this.groupBy;
    }

    public void setGroupBy(String[] groupBy)
    {
        this.groupBy = groupBy;
    }

    /**
     * 获取分组条件
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return
     */
    public Map<String,Object> getHaving()
    {
        return  this.having;
    }

    public void setHaving(Map<String,Object> having)
    {
        this.having = having;
    }

    /**
     * 获取是否加锁
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return
     */
    public boolean getLock()
    {
        return  this.lock;
    }

    public void setLock(boolean lock)
    {
        this.lock = lock;
    }

    /**
     * 获取插入数据
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return
     */
    public List<Map<String,Object>> getData()
    {
        return this.data;
    }

    public void setData(Map<String,Object> data)
    {
        if (this.data == null) {
            this.data = new ArrayList<>();
        }

        this.data.add(data);
    }

    /**
     * 获取插入数据
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return
     */
    public Map<String,Object> getWhere()
    {
        return this.where;
    }

    public void setWhere(Map<String,Object> where )
    {
        this.where = where;
    }

    /**
     * 获取行数范围
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return
     */
    public int [] getLimit()
    {
        int[] limit = {this.limit,this.offset};
        return limit;
    }

    public void setLimit(int limit)
    {
        this.limit = limit;
    }

    public void setOffset(int offset)
    {
        this.offset = offset;
    }

    public void addUnion(Query query)
    {

        if (this.union == null) {
            this.union = new Union();
        }

        this.union.addQuery(query);
    }

    public void addUnion(Query query,String unionMode)
    {

        if (this.union == null) {
            this.union = new Union(unionMode);
        } else {
            this.union.setUnionMode(unionMode);
        }

        this.union.addQuery(query);
    }

    public Union getUnion()
    {
        return this.union;
    }

    public void setToQuery(boolean toQuery)
    {
        this.toQuery = toQuery;
    }

    public boolean getToQuery()
    {
        return this.toQuery;
    }

    public void setEntity(Class entity)
    {
        this.entity = entity;
    }

    public Class getEntity()
    {
        return this.entity;
    }

    /**
     * 设置QueryBuilder 构建方法参数
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @param params 构建方法参数
     * @return
     */
    public void setBuildParams(Object[] params)
    {
        this.buildParams = params;
    }

    /**
     * 设置QueryBuilder 构建方法
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @param buildMethod 方法名
     * @return
     */
    public void setBuildMethod(String buildMethod)
    {
        this.buildMethod = buildMethod;
    }

    /**
     * 考虑一份数据
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public Query cloneQuery(Map<String,Object> options)
    {
        //  读取此类所有属性
        Map<String,Object> attrs = this.getAttrs();
        if (options != null) {
            attrs.putAll(options);
        }

        return new Query(attrs);
    }

    /**
     * 获取对象属性
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public Map<String,Object> getAttrs()
    {
        if (fields == null) {
            fields = this.getClass().getDeclaredFields();
        }

        Map<String,Object> attrs = new HashMap<>();

        for (Field field:fields) {
            try {
                field.setAccessible(true);
                attrs.put(field.getName(),field.get(this));
            } catch (Exception ex) {

            }
        }

        return attrs;
    }

}
